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>
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()
244 proto = fou->protocol; in fou_gro_receive()
249 * treating the GRE tunnel header as though it is a UDP protocol in fou_gro_receive()
252 NAPI_GRO_CB(skb)->encap_mark = 0; in fou_gro_receive()
255 NAPI_GRO_CB(skb)->is_fou = 1; in fou_gro_receive()
257 offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; in fou_gro_receive()
259 if (!ops || !ops->callbacks.gro_receive) in fou_gro_receive()
262 pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); in fou_gro_receive()
278 err = -ENOENT; in fou_gro_complete()
282 proto = fou->protocol; in fou_gro_complete()
284 offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; in fou_gro_complete()
286 if (WARN_ON(!ops || !ops->callbacks.gro_complete)) { in fou_gro_complete()
287 err = -ENOSYS; in fou_gro_complete()
291 err = ops->callbacks.gro_complete(skb, nhoff); in fou_gro_complete()
308 if (skb->remcsum_offload) in gue_gro_remcsum()
311 if (!NAPI_GRO_CB(skb)->csum_valid) in gue_gro_remcsum()
317 skb->remcsum_offload = 1; in gue_gro_remcsum()
351 switch (guehdr->version) { in gue_gro_receive()
355 switch (((struct iphdr *)guehdr)->version) { in gue_gro_receive()
370 optlen = guehdr->hlen << 2; in gue_gro_receive()
379 if (unlikely(guehdr->control) || guehdr->version != 0 || in gue_gro_receive()
385 /* Adjust NAPI_GRO_CB(skb)->csum to account for guehdr, in gue_gro_receive()
392 if (guehdr->flags & GUE_FLAG_PRIV) { in gue_gro_receive()
400 !!(fou->flags & in gue_gro_receive()
417 if (!NAPI_GRO_CB(p)->same_flow) in gue_gro_receive()
420 guehdr2 = (struct guehdr *)(p->data + off); in gue_gro_receive()
425 if (guehdr->word != guehdr2->word) { in gue_gro_receive()
426 NAPI_GRO_CB(p)->same_flow = 0; in gue_gro_receive()
431 if (guehdr->hlen && memcmp(&guehdr[1], &guehdr2[1], in gue_gro_receive()
432 guehdr->hlen << 2)) { in gue_gro_receive()
433 NAPI_GRO_CB(p)->same_flow = 0; in gue_gro_receive()
438 proto = guehdr->proto_ctype; in gue_gro_receive()
445 * treating the GRE tunnel header as though it is a UDP protocol in gue_gro_receive()
448 NAPI_GRO_CB(skb)->encap_mark = 0; in gue_gro_receive()
451 NAPI_GRO_CB(skb)->is_fou = 1; in gue_gro_receive()
453 offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; in gue_gro_receive()
455 if (!ops || !ops->callbacks.gro_receive) in gue_gro_receive()
458 pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); in gue_gro_receive()
469 struct guehdr *guehdr = (struct guehdr *)(skb->data + nhoff); in gue_gro_complete()
474 int err = -ENOENT; in gue_gro_complete()
476 switch (guehdr->version) { in gue_gro_complete()
478 proto = guehdr->proto_ctype; in gue_gro_complete()
479 guehlen = sizeof(*guehdr) + (guehdr->hlen << 2); in gue_gro_complete()
482 switch (((struct iphdr *)guehdr)->version) { in gue_gro_complete()
497 offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; in gue_gro_complete()
499 if (WARN_ON(!ops || !ops->callbacks.gro_complete)) in gue_gro_complete()
502 err = ops->callbacks.gro_complete(skb, nhoff + guehlen); in gue_gro_complete()
512 struct sock *sk = fou->sock->sk; in fou_cfg_cmp()
513 struct udp_port_cfg *udp_cfg = &cfg->udp_config; in fou_cfg_cmp()
515 if (fou->family != udp_cfg->family || in fou_cfg_cmp()
516 fou->port != udp_cfg->local_udp_port || in fou_cfg_cmp()
517 sk->sk_dport != udp_cfg->peer_udp_port || in fou_cfg_cmp()
518 sk->sk_bound_dev_if != udp_cfg->bind_ifindex) in fou_cfg_cmp()
521 if (fou->family == AF_INET) { in fou_cfg_cmp()
522 if (sk->sk_rcv_saddr != udp_cfg->local_ip.s_addr || in fou_cfg_cmp()
523 sk->sk_daddr != udp_cfg->peer_ip.s_addr) in fou_cfg_cmp()
529 if (ipv6_addr_cmp(&sk->sk_v6_rcv_saddr, &udp_cfg->local_ip6) || in fou_cfg_cmp()
530 ipv6_addr_cmp(&sk->sk_v6_daddr, &udp_cfg->peer_ip6)) in fou_cfg_cmp()
546 mutex_lock(&fn->fou_lock); in fou_add_to_port_list()
547 list_for_each_entry(fout, &fn->fou_list, list) { in fou_add_to_port_list()
549 mutex_unlock(&fn->fou_lock); in fou_add_to_port_list()
550 return -EALREADY; in fou_add_to_port_list()
554 list_add(&fou->list, &fn->fou_list); in fou_add_to_port_list()
555 mutex_unlock(&fn->fou_lock); in fou_add_to_port_list()
562 struct socket *sock = fou->sock; in fou_release()
564 list_del(&fou->list); in fou_release()
579 /* Open UDP socket */ in fou_create()
580 err = udp_sock_create(net, &cfg->udp_config, &sock); in fou_create()
587 err = -ENOMEM; in fou_create()
591 sk = sock->sk; in fou_create()
593 fou->port = cfg->udp_config.local_udp_port; in fou_create()
594 fou->family = cfg->udp_config.family; in fou_create()
595 fou->flags = cfg->flags; in fou_create()
596 fou->type = cfg->type; in fou_create()
597 fou->sock = sock; in fou_create()
605 switch (cfg->type) { in fou_create()
610 fou->protocol = cfg->protocol; in fou_create()
618 err = -EINVAL; in fou_create()
624 sk->sk_allocation = GFP_ATOMIC; in fou_create()
646 int err = -EINVAL; in fou_destroy()
649 mutex_lock(&fn->fou_lock); in fou_destroy()
650 list_for_each_entry(fou, &fn->fou_list, list) { in fou_destroy()
657 mutex_unlock(&fn->fou_lock); in fou_destroy()
674 cfg->udp_config.family = AF_INET; in parse_nl_config()
676 if (info->attrs[FOU_ATTR_AF]) { in parse_nl_config()
677 u8 family = nla_get_u8(info->attrs[FOU_ATTR_AF]); in parse_nl_config()
683 cfg->udp_config.ipv6_v6only = 1; in parse_nl_config()
686 return -EAFNOSUPPORT; in parse_nl_config()
689 cfg->udp_config.family = family; in parse_nl_config()
692 if (info->attrs[FOU_ATTR_PORT]) { in parse_nl_config()
693 port = nla_get_be16(info->attrs[FOU_ATTR_PORT]); in parse_nl_config()
694 cfg->udp_config.local_udp_port = port; in parse_nl_config()
697 if (info->attrs[FOU_ATTR_IPPROTO]) in parse_nl_config()
698 cfg->protocol = nla_get_u8(info->attrs[FOU_ATTR_IPPROTO]); in parse_nl_config()
700 if (info->attrs[FOU_ATTR_TYPE]) in parse_nl_config()
701 cfg->type = nla_get_u8(info->attrs[FOU_ATTR_TYPE]); in parse_nl_config()
703 if (info->attrs[FOU_ATTR_REMCSUM_NOPARTIAL]) in parse_nl_config()
704 cfg->flags |= FOU_F_REMCSUM_NOPARTIAL; in parse_nl_config()
706 if (cfg->udp_config.family == AF_INET) { in parse_nl_config()
707 if (info->attrs[FOU_ATTR_LOCAL_V4]) { in parse_nl_config()
708 attr = info->attrs[FOU_ATTR_LOCAL_V4]; in parse_nl_config()
709 cfg->udp_config.local_ip.s_addr = nla_get_in_addr(attr); in parse_nl_config()
713 if (info->attrs[FOU_ATTR_PEER_V4]) { in parse_nl_config()
714 attr = info->attrs[FOU_ATTR_PEER_V4]; in parse_nl_config()
715 cfg->udp_config.peer_ip.s_addr = nla_get_in_addr(attr); in parse_nl_config()
720 if (info->attrs[FOU_ATTR_LOCAL_V6]) { in parse_nl_config()
721 attr = info->attrs[FOU_ATTR_LOCAL_V6]; in parse_nl_config()
722 cfg->udp_config.local_ip6 = nla_get_in6_addr(attr); in parse_nl_config()
726 if (info->attrs[FOU_ATTR_PEER_V6]) { in parse_nl_config()
727 attr = info->attrs[FOU_ATTR_PEER_V6]; in parse_nl_config()
728 cfg->udp_config.peer_ip6 = nla_get_in6_addr(attr); in parse_nl_config()
735 if (info->attrs[FOU_ATTR_PEER_PORT]) { in parse_nl_config()
736 port = nla_get_be16(info->attrs[FOU_ATTR_PEER_PORT]); in parse_nl_config()
737 cfg->udp_config.peer_udp_port = port; in parse_nl_config()
739 return -EINVAL; in parse_nl_config()
743 if (info->attrs[FOU_ATTR_IFINDEX]) { in parse_nl_config()
745 return -EINVAL; in parse_nl_config()
747 ifindex = nla_get_s32(info->attrs[FOU_ATTR_IFINDEX]); in parse_nl_config()
749 cfg->udp_config.bind_ifindex = ifindex; in parse_nl_config()
783 struct sock *sk = fou->sock->sk; in fou_fill_info()
785 if (nla_put_u8(msg, FOU_ATTR_AF, fou->sock->sk->sk_family) || in fou_fill_info()
786 nla_put_be16(msg, FOU_ATTR_PORT, fou->port) || in fou_fill_info()
787 nla_put_be16(msg, FOU_ATTR_PEER_PORT, sk->sk_dport) || in fou_fill_info()
788 nla_put_u8(msg, FOU_ATTR_IPPROTO, fou->protocol) || in fou_fill_info()
789 nla_put_u8(msg, FOU_ATTR_TYPE, fou->type) || in fou_fill_info()
790 nla_put_s32(msg, FOU_ATTR_IFINDEX, sk->sk_bound_dev_if)) in fou_fill_info()
791 return -1; in fou_fill_info()
793 if (fou->flags & FOU_F_REMCSUM_NOPARTIAL) in fou_fill_info()
795 return -1; in fou_fill_info()
797 if (fou->sock->sk->sk_family == AF_INET) { in fou_fill_info()
798 if (nla_put_in_addr(msg, FOU_ATTR_LOCAL_V4, sk->sk_rcv_saddr)) in fou_fill_info()
799 return -1; in fou_fill_info()
801 if (nla_put_in_addr(msg, FOU_ATTR_PEER_V4, sk->sk_daddr)) in fou_fill_info()
802 return -1; in fou_fill_info()
806 &sk->sk_v6_rcv_saddr)) in fou_fill_info()
807 return -1; in fou_fill_info()
809 if (nla_put_in6_addr(msg, FOU_ATTR_PEER_V6, &sk->sk_v6_daddr)) in fou_fill_info()
810 return -1; in fou_fill_info()
824 return -ENOMEM; in fou_dump_info()
834 return -EMSGSIZE; in fou_dump_info()
853 return -EINVAL; in fou_nl_get_doit()
857 return -EINVAL; in fou_nl_get_doit()
861 return -ENOMEM; in fou_nl_get_doit()
863 ret = -ESRCH; in fou_nl_get_doit()
864 mutex_lock(&fn->fou_lock); in fou_nl_get_doit()
865 list_for_each_entry(fout, &fn->fou_list, list) { in fou_nl_get_doit()
867 ret = fou_dump_info(fout, info->snd_portid, in fou_nl_get_doit()
868 info->snd_seq, 0, msg, in fou_nl_get_doit()
869 info->genlhdr->cmd); in fou_nl_get_doit()
873 mutex_unlock(&fn->fou_lock); in fou_nl_get_doit()
886 struct net *net = sock_net(skb->sk); in fou_nl_get_dumpit()
891 mutex_lock(&fn->fou_lock); in fou_nl_get_dumpit()
892 list_for_each_entry(fout, &fn->fou_list, list) { in fou_nl_get_dumpit()
893 if (idx++ < cb->args[0]) in fou_nl_get_dumpit()
895 ret = fou_dump_info(fout, NETLINK_CB(cb->skb).portid, in fou_nl_get_dumpit()
896 cb->nlh->nlmsg_seq, NLM_F_MULTI, in fou_nl_get_dumpit()
901 mutex_unlock(&fn->fou_lock); in fou_nl_get_dumpit()
903 cb->args[0] = idx; in fou_nl_get_dumpit()
904 return skb->len; in fou_nl_get_dumpit()
933 if (e->flags & TUNNEL_ENCAP_FLAG_REMCSUM) { in gue_encap_hlen()
953 *sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev), in __fou_build_header()
969 if ((e->flags & TUNNEL_ENCAP_FLAG_REMCSUM) && in __gue_build_header()
970 skb->ip_summed == CHECKSUM_PARTIAL) { in __gue_build_header()
983 *sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev), in __gue_build_header()
990 guehdr = (struct guehdr *)skb->data; in __gue_build_header()
992 guehdr->control = 0; in __gue_build_header()
993 guehdr->version = 0; in __gue_build_header()
994 guehdr->hlen = optlen >> 2; in __gue_build_header()
995 guehdr->flags = 0; in __gue_build_header()
996 guehdr->proto_ctype = *protocol; in __gue_build_header()
1003 guehdr->flags |= GUE_FLAG_PRIV; in __gue_build_header()
1012 return -EINVAL; in __gue_build_header()
1014 csum_start -= hdrlen; in __gue_build_header()
1016 pd[1] = htons(csum_start + skb->csum_offset); in __gue_build_header()
1019 skb->ip_summed = CHECKSUM_NONE; in __gue_build_header()
1020 skb->encapsulation = 0; in __gue_build_header()
1045 uh->dest = e->dport; in fou_build_udp()
1046 uh->source = sport; in fou_build_udp()
1047 uh->len = htons(skb->len); in fou_build_udp()
1048 udp_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM), skb, in fou_build_udp()
1049 fl4->saddr, fl4->daddr, skb->len); in fou_build_udp()
1057 int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM ? SKB_GSO_UDP_TUNNEL_CSUM : in fou_build_header()
1074 int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM ? SKB_GSO_UDP_TUNNEL_CSUM : in gue_build_header()
1092 if (ipprot && ipprot->err_handler) { in gue_err_proto_handler()
1093 if (!ipprot->err_handler(skb, info)) in gue_err_proto_handler()
1097 return -ENOENT; in gue_err_proto_handler()
1109 return -EINVAL; in gue_err()
1113 switch (guehdr->version) { in gue_err()
1118 skb_set_transport_header(skb, -(int)sizeof(struct icmphdr)); in gue_err()
1120 switch (((struct iphdr *)guehdr)->version) { in gue_err()
1130 ret = -EOPNOTSUPP; in gue_err()
1135 return -EOPNOTSUPP; in gue_err()
1138 if (guehdr->control) in gue_err()
1139 return -ENOENT; in gue_err()
1141 optlen = guehdr->hlen << 2; in gue_err()
1144 return -EINVAL; in gue_err()
1148 return -EINVAL; in gue_err()
1150 /* Handling exceptions for direct UDP encapsulation in GUE would lead to in gue_err()
1154 if (guehdr->proto_ctype == IPPROTO_UDP || in gue_err()
1155 guehdr->proto_ctype == IPPROTO_UDPLITE) in gue_err()
1156 return -EOPNOTSUPP; in gue_err()
1158 skb_set_transport_header(skb, -(int)sizeof(struct icmphdr)); in gue_err()
1159 ret = gue_err_proto_handler(guehdr->proto_ctype, skb, info); in gue_err()
1222 INIT_LIST_HEAD(&fn->fou_list); in fou_init_net()
1223 mutex_init(&fn->fou_lock); in fou_init_net()
1233 mutex_lock(&fn->fou_lock); in fou_exit_net()
1234 list_for_each_entry_safe(fou, next, &fn->fou_list, list) in fou_exit_net()
1236 mutex_unlock(&fn->fou_lock); in fou_exit_net()
1285 MODULE_DESCRIPTION("Foo over UDP");